﻿using Markdig;
using Microsoft.AspNetCore.Http;
using RsCms.Entities;
using RsCode;

namespace RsCms.Core.Posts
{
    public class PostDomainService:IPostDomainService
    {
        IPostsRepository repository;
        IHttpContextAccessor httpContextAccessor;
        public PostDomainService(IPostsRepository repository,
            IHttpContextAccessor  httpContextAccessor) {
            this.repository = repository;
            this.httpContextAccessor = httpContextAccessor;
        }

        string LoginUserId
        {
            get
            {
                var claims = httpContextAccessor?.HttpContext?.User.Claims;
                return claims?.First(x => x.Type == "UserId").Value??"";
            }
        }
        public async Task<PageData<Entities.Posts>> PagePublishAsync(int page,int pageSize, string[]date=null)
        {
            if (pageSize > 30) pageSize = 30;

            if (date == null)
            {
                var select = repository.PostStore.Select.Where(x =>x.Type=="post"&& x.Visibility == "public" && x.Status == "published").OrderByDescending(x => x.CreatedAt);
                var info = await repository.PostStore.PageAsync(page, pageSize, select);
                return info;
            }
            else
            {
                try
                {
                    DateTime startDate = DateTimeHelper.GetStartDateTime(Convert.ToDateTime(date[0]));
                    DateTime endDate = DateTimeHelper.GetEndDateTime(Convert.ToDateTime(date[1]));

                    var select = repository.PostStore.Select.Where(x => x.Visibility == "public" && x.Status == "published" && (x.CreatedAt >= startDate && x.CreatedAt <= endDate)).OrderByDescending(x => x.CreatedAt);
                    return await repository.PostStore.PageAsync(page, pageSize, select);
                }
                catch (Exception )
                {

                    return new PageData<Entities.Posts> { };
                }
               
            }
          
        }

        public async Task<Entities.Posts> GetPostsAsync(string IdOrSlug)
        {
            var info= await repository.PostStore.Select.IncludeMany(x=>x.posts_metas).Where(x => (x.Id == IdOrSlug||x.Slug==IdOrSlug)&&x.Type=="post").ToOneAsync();
            if(info!=null)
            {
                var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
                
                info.Html = Markdown.ToHtml(info.Markdown, pipeline);
            }
            return info;
        }

        public async Task<Entities.Posts> GetPostsBySlugAsync(string slug)
        {
            var info= await repository.PostStore.Where(x=>x.Slug==slug && x.Type == "post").ToOneAsync();
            if (info != null)
            {
                var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
                info.Html = Markdown.ToHtml(info.Markdown, pipeline);
            }
            return info;
        }

        public async Task< Entities.Posts> SaveAsync(Entities.Posts posts)
        {
            if(posts==null)
            {
                throw new AppException("提交参数不能为空");
            }

           
            var info = await repository.PostStore.Where(x => x.Id == posts.Id).ToOneAsync();
            if (info==null)
            {
                posts.Init(LoginUserId); 
                return repository.PostStore.Insert(posts);
            }else
            {
                
                posts.CanonicalUrl= posts.CanonicalUrl != info.CanonicalUrl ? posts.CanonicalUrl:info.CanonicalUrl;
                posts.CodeinjectionFoot = posts.CodeinjectionFoot != info.CodeinjectionFoot ? posts.CodeinjectionFoot : info.CodeinjectionFoot;
                posts.CodeinjectionHead = posts.CodeinjectionHead != info.CodeinjectionHead ? posts.CodeinjectionHead : info.CodeinjectionHead;
                posts.CommentId = posts.CommentId != info.CommentId ? posts.CommentId : info.CommentId;
                posts.CustomExcerpt = posts.CustomExcerpt != info.CustomExcerpt ? posts.CustomExcerpt : info.CustomExcerpt;
                posts.CustomTemplate = posts.CustomTemplate != info.CustomTemplate ? posts.CustomTemplate : info.CustomTemplate;
                posts.EmailRecipientFilter = posts.EmailRecipientFilter != info.EmailRecipientFilter ? posts.EmailRecipientFilter : info.EmailRecipientFilter;
                posts.Featured = posts.Featured != info.Featured ? posts.Featured : info.Featured;
                posts.FeatureImage = posts.FeatureImage != info.FeatureImage ? posts.FeatureImage : info.FeatureImage;
                posts.Html = posts.Html != info.Html ? posts.Html : info.Html;
                posts.Markdown = posts.Markdown != info.Markdown ? posts.Markdown : info.Markdown;
                posts.Lexical = posts.Lexical != info.Lexical ? posts.Lexical : info.Lexical;
                posts.Locale = posts.Locale != info.Locale ? posts.Locale : info.Locale;
                posts.Mobiledoc = posts.Mobiledoc != info.Mobiledoc ? posts.Mobiledoc : info.Mobiledoc; 
                posts.Plaintext = posts.Plaintext != info.Plaintext ? posts.Plaintext : info.Plaintext;
                posts.ShowTitleAndFeatureImage = posts.ShowTitleAndFeatureImage != info.ShowTitleAndFeatureImage ? posts.ShowTitleAndFeatureImage : info.ShowTitleAndFeatureImage;
                posts.Slug = posts.Slug != info.Slug ? posts.Slug : info.Slug;
                posts.Title = posts.Title != info.Title ? posts.Title : info.Title;
                posts.Type = posts.Type != info.Type ? posts.Type : info.Type;
                posts.UpdatedBy = posts.UpdatedBy != info.UpdatedBy ? posts.UpdatedBy : info.UpdatedBy;
                posts.Visibility = posts.Visibility != info.Visibility ? posts.Visibility : info.Visibility; 
                posts.Tags = posts.Tags != info.Tags ? posts.Tags : info.Tags;
                posts.Status = posts.Status != info.Status ? posts.Status : info.Status;

                posts.Uuid = LoginUserId;
                posts.CreatedAt = info.CreatedAt;
                posts.CreatedBy= info.CreatedBy;   
                posts.PublishedBy=info.PublishedBy;
                posts.PublishedAt=info.PublishedAt; 
                posts.UpdatedAt = DateTime.Now;
                 
                repository.PostStore.Update(posts);
                return posts;
            }
             
        }

        public async Task<PageData<Entities.Posts>> PageDraftsAsync(int page, int pageSize, string[] date = null)
        {
            if (pageSize > 30) pageSize = 30;

            if(date==null)
            {
                var select = repository.PostStore.Select.Where(x => x.Type == "post" && x.Status == "draft").OrderByDescending(x => x.CreatedAt);
                return await repository.PostStore.PageAsync(page, pageSize, select);
            }
            else
            {
                try
                {
                    DateTime startDate = DateTimeHelper.GetStartDateTime(Convert.ToDateTime(date[0]));
                    DateTime endDate = DateTimeHelper.GetEndDateTime(Convert.ToDateTime(date[1]));

                    var select = repository.PostStore.Select.Where(x => x.Type == "post" && x.Visibility == "draft"  && (x.CreatedAt >= startDate && x.CreatedAt <= endDate)).OrderByDescending(x => x.CreatedAt);
                    return await repository.PostStore.PageAsync(page, pageSize, select);
                }
                catch (Exception)
                {

                    return new PageData<Entities.Posts> { };
                }
            }
        }

        public async Task<PageData<Entities.Posts>> PageScheduledAsync(int page, int pageSize, string[] date = null)
        {
            if (pageSize > 30) pageSize = 30;

            if (date == null)
            {
                var select = repository.PostStore.Select.Where(x => x.Type == "post" && x.Status == "scheduled").OrderByDescending(x => x.CreatedAt);
                return await repository.PostStore.PageAsync(page, pageSize, select);
            }
            else
            {
                try
                {
                    DateTime startDate = DateTimeHelper.GetStartDateTime(Convert.ToDateTime(date[0]));
                    DateTime endDate = DateTimeHelper.GetEndDateTime(Convert.ToDateTime(date[1]));

                    var select = repository.PostStore.Select.Where(x => x.Type == "post" && x.Status == "published" && (x.CreatedAt >= startDate && x.CreatedAt <= endDate)).OrderByDescending(x => x.CreatedAt);
                    return await repository.PostStore.PageAsync(page, pageSize, select);
                }
                catch (Exception)
                {
                    return new PageData<Entities.Posts> { };
                }
            }
        }

        public async Task<PageData<Entities.Posts>>PageAsync(int page,int pageSize)
        {
            if (pageSize > 30) pageSize = 30;

            var select = repository.PostStore.Select.Where(x=> x.Type == "post" ).OrderByDescending(x => x.CreatedAt);
            return await repository.PostStore.PageAsync(page, pageSize, select);
        }

        public async Task<PageData<Entities.Posts>> PageAsync(int page, int pageSize, string tagId)
        {
            if (pageSize > 30) pageSize = 30;

            var select = repository.PostStore.Select.IncludeMany(x=>x.posts_metas).Where(x => x.Type == "post"&&x.Tags.Contains(tagId)).OrderByDescending(x => x.CreatedAt);
            return await repository.PostStore.PageAsync(page, pageSize, select);
        }

        public async Task<PostsMeta> SaveAsync(PostsMeta postsMeta)
        {
            var info =await repository.PostMetaStore.Select.Where(x => x.PostId == postsMeta.PostId).ToOneAsync();
            if(info==null)
            {
                info = new PostsMeta()
                {
                     Id=Guid.NewGuid().ToString("N"),
                     PostId= postsMeta.PostId,
                     MetaTitle=postsMeta.MetaTitle,
                     MetaDescription=postsMeta.MetaDescription,
                };
                repository.PostMetaStore.Insert(info);
            }else
            {
                info.MetaTitle = postsMeta.MetaTitle;
                info.MetaDescription= postsMeta.MetaDescription;
                repository.PostMetaStore.Update(info);
            }
            info = await repository.PostMetaStore.Select.Where(x => x.PostId == postsMeta.PostId).ToOneAsync();
            return info;
        }
    }
}
